<script setup lang="ts">
import { ref, watch, computed } from 'vue'

type UnitDef = { label: string; value: string }

const conversionType = ref<'length' | 'weight' | 'area' | 'volume' | 'temperature'>('length')
const fromValue = ref(1)
const toValue = ref(0)
const fromUnit = ref('m')
const toUnit = ref('km')

const unitOptions: Record<'length' | 'weight' | 'area' | 'volume' | 'temperature', UnitDef[]> = {
  length: [
    { label: '米 (m)', value: 'm' },
    { label: '千米 (km)', value: 'km' },
    { label: '厘米 (cm)', value: 'cm' },
    { label: '毫米 (mm)', value: 'mm' },
    { label: '英寸 (in)', value: 'in' },
    { label: '英尺 (ft)', value: 'ft' },
  ],
  weight: [
    { label: '千克 (kg)', value: 'kg' },
    { label: '克 (g)', value: 'g' },
    { label: '磅 (lb)', value: 'lb' },
  ],
  area: [
    { label: '平方米 (m²)', value: 'm2' },
    { label: '平方千米 (km²)', value: 'km2' },
    { label: '平方厘米 (cm²)', value: 'cm2' },
  ],
  volume: [
    { label: '升 (L)', value: 'l' },
    { label: '毫升 (mL)', value: 'ml' },
    { label: '立方米 (m³)', value: 'm3' },
  ],
  temperature: [
    { label: '摄氏度 (°C)', value: 'c' },
    { label: '华氏度 (°F)', value: 'f' },
    { label: '开尔文 (K)', value: 'k' },
  ],
}

const factors: Record<'length' | 'weight' | 'area' | 'volume', Record<string, number>> = {
  length: {
    m: 1,
    km: 1000,
    cm: 0.01,
    mm: 0.001,
    in: 0.0254,
    ft: 0.3048,
  },
  weight: {
    kg: 1,
    g: 0.001,
    lb: 0.45359237,
  },
  area: {
    m2: 1,
    km2: 1_000_000,
    cm2: 0.0001,
  },
  volume: {
    l: 0.001, // 升转立方米
    ml: 0.000001,
    m3: 1,
  },
}

const currentOptions = computed<UnitDef[]>(() => unitOptions[conversionType.value])

function convert() {
  if (conversionType.value === 'temperature') {
    toValue.value = convertTemperature(fromValue.value, fromUnit.value, toUnit.value)
    return
  }
  const type = conversionType.value
  const baseMeters = fromValue.value * (factors[type][fromUnit.value] ?? 1)
  toValue.value = baseMeters / (factors[type][toUnit.value] ?? 1)
}

function convertTemperature(val: number, from: string, to: string) {
  // 先转摄氏度
  let c = val
  if (from === 'f') c = (val - 32) * (5 / 9)
  else if (from === 'k') c = val - 273.15
  // 再由摄氏度转目标单位
  if (to === 'c') return c
  if (to === 'f') return c * (9 / 5) + 32
  if (to === 'k') return c + 273.15
  return c
}

function onTypeChange() {
  const opts = currentOptions.value
  fromUnit.value = opts[0]?.value ?? ''
  toUnit.value = opts[1]?.value ?? ''
  convert()
}

function swapUnits() {
  const fu = fromUnit.value
  fromUnit.value = toUnit.value
  toUnit.value = fu
  convert()
}

watch([conversionType, fromValue, fromUnit, toUnit], convert, { immediate: true })
</script>

<template>
  <div class="space-y-4">
    <div>
      <label class="block text-sm font-medium mb-1">转换类型：</label>
      <select
        v-model="conversionType"
        @change="onTypeChange"
        class="w-full p-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-primary/50"
      >
        <option value="length">长度</option>
        <option value="weight">重量</option>
        <option value="area">面积</option>
        <option value="volume">体积</option>
        <option value="temperature">温度</option>
      </select>
    </div>
    <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
      <div>
        <label class="block text-sm font-medium mb-1">从：</label>
        <div class="flex">
          <input
            type="number"
            v-model.number="fromValue"
            class="flex-1 p-2 border border-gray-300 dark:border-gray-600 rounded-l-lg bg-white dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-primary/50"
          />
          <select
            v-model="fromUnit"
            class="p-2 border border-gray-300 dark:border-gray-600 border-l-0 rounded-r-lg bg-white dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-primary/50"
          >
            <option v-for="opt in currentOptions" :key="opt.value" :value="opt.value">{{ opt.label }}</option>
          </select>
        </div>
      </div>
      <div>
        <label class="block text-sm font-medium mb-1">到：</label>
        <div class="flex">
          <input
            type="number"
            :value="toValue"
            readonly
            class="flex-1 p-2 border border-gray-300 dark:border-gray-600 rounded-l-lg bg-white dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-primary/50"
          />
          <select
            v-model="toUnit"
            class="p-2 border border-gray-300 dark:border-gray-600 border-l-0 rounded-r-lg bg-white dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-primary/50"
          >
            <option v-for="opt in currentOptions" :key="opt.value" :value="opt.value">{{ opt.label }}</option>
          </select>
        </div>
      </div>
    </div>
    <button
      class="w-full py-2 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800"
      @click="swapUnits"
    >
      <i class="fa fa-refresh mr-1"></i> 交换单位
    </button>
  </div>
</template>

<style scoped></style>